﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Text;
using System.Windows.Forms;
using MigratorCore.Actions;
using System.Threading;
using MigratorCore.Status;
using System.Xml;
using MigratorCore.Bases;

namespace MigratorWizard
{
    public partial class Progress : UserControl
    {
        public Progress()
        {
            InitializeComponent();
        }

        private Main main;

        public Main Main
        {
            set 
            { 
                main = value; 
                main.Migrator.Change += new MigratorCore.Bases.MirgratorChangedEventHandler(Migrator_Change); 
                main.FormClosing += new FormClosingEventHandler(main_FormClosing);
                main.NextClick += new NextClick(main_NextClick);
            }
        }

        void main_NextClick(object sender, EventArgs e)
        {
            if (this.Visible && this.main != null)
            {
                if (MessageBox.Show("Do you want to save the log file?", "Question?", MessageBoxButtons.YesNo, MessageBoxIcon.Question, MessageBoxDefaultButton.Button2) == DialogResult.Yes)
                    saveFileDialog1.ShowDialog();
            }
        }

        void main_FormClosing(object sender, FormClosingEventArgs e)
        {
            main.Migrator.Change -= new MigratorCore.Bases.MirgratorChangedEventHandler(Migrator_Change);
        }

        delegate void SetCallback();

        void Migrator_Change()
        {
            if (Visible && main != null)
            {
                if (this.progs.InvokeRequired | this.main.InvokeRequired | this.label7.InvokeRequired)
                {
                    SetCallback d = new SetCallback(Migrator_Change);
                    try
                    {
                        this.Invoke(d);
                    }
                    catch { }
                }
                else
                {
                    for (int x = 0; x < main.Migrator.SourceActions.Count; x++)
                    {
                        ISourceAction source = main.Migrator.SourceActions[x];
                        try
                        {
                            VistaControls.ProgressBar p = progs.Controls.Find("prog" + source.Name.Replace(" ", "").Trim(), true)[0] as VistaControls.ProgressBar;
                            p.Value = source.Status.Completed;
                            foreach (Event e in source.Status)
                                if (e.EventType == EventType.CriticalError) p.ProgressState = VistaControls.ProgressBar.States.Error;
                                else if (e.EventType == EventType.Duplicate) p.ProgressState = VistaControls.ProgressBar.States.Paused;
                                else if (e.EventType == EventType.MissingData) p.ProgressState = VistaControls.ProgressBar.States.Paused;
                        }
                        catch { }
                        IDestinationAction des = main.Migrator.DestinationActions[x];
                        try {
                            VistaControls.ProgressBar p2 = progs.Controls.Find("prog" + des.Name.Replace(" ", "").Trim(), true)[0] as VistaControls.ProgressBar;
                            p2.Value = des.Status.Completed;
                            foreach (Event e in des.Status)
                                if (e.EventType == EventType.CriticalError) p2.ProgressState = VistaControls.ProgressBar.States.Error;
                                else if (e.EventType == EventType.Duplicate) p2.ProgressState = VistaControls.ProgressBar.States.Paused;
                                else if (e.EventType == EventType.MissingData) p2.ProgressState = VistaControls.ProgressBar.States.Paused;
                        }
                        catch { }
                    }
                }
            }
        }

        private void Progress_VisibleChanged(object sender, EventArgs e)
        {
            if (Visible && main != null)
            {
                main.EnableBack = false;
                main.EnableNext = false;
                main.Text = "The Migrator Project - Migrating";
                progs.Controls.Clear();
                progs.RowStyles.Clear();
                progs.RowCount = 0;
                for (int x = 0; x < main.Migrator.SourceActions.Count; x++)
                {
                    #region Source
                    ISourceAction source = main.Migrator.SourceActions[x];
                    Label l = new Label();
                    l.Text = source.Name;
                    l.Dock = DockStyle.Fill;
                    l.TextAlign = ContentAlignment.MiddleLeft;
                    VistaControls.ProgressBar p = new VistaControls.ProgressBar();
                    p.Name = "prog" + source.Name.Replace(" ", "").Trim();
                    p.Value = source.Status.Completed;
                    p.Maximum = 100;
                    p.Minimum = 0;
                    p.Step = 1;
                    p.Dock = DockStyle.Fill;
                    p.Margin = new Padding(p.Margin.Left, p.Margin.Top, 1, p.Margin.Bottom);
                    #endregion
                    #region Destination
                    IDestinationAction des = main.Migrator.DestinationActions[x];
                    Label l2 = new Label();
                    l2.Text = des.Name;
                    VistaControls.ProgressBar p2 = new VistaControls.ProgressBar();
                    p2.Name = "prog" + des.Name.Replace(" ", "").Trim();
                    p2.Value = des.Status.Completed;
                    p2.Maximum = 100;
                    p2.Minimum = 0;
                    p2.Step = 1;
                    p2.Dock = DockStyle.Fill;
                    p2.Margin = new Padding(1, p2.Margin.Top, p2.Margin.Right, p2.Margin.Bottom);
                    #endregion
                    #region Common
                    LinkLabel link = new LinkLabel();
                    link.Text = "View Log";
                    link.Name = "log" + x;
                    link.Dock = DockStyle.Left;
                    link.AutoSize = true;
                    link.TextAlign = ContentAlignment.MiddleCenter;
                    link.LinkColor = System.Drawing.SystemColors.Highlight;
                    link.DisabledLinkColor = System.Drawing.SystemColors.InactiveCaption;
                    link.ActiveLinkColor = System.Drawing.SystemColors.HotTrack;
                    link.VisitedLinkColor = System.Drawing.SystemColors.ActiveCaption;
                    link.LinkClicked += new System.Windows.Forms.LinkLabelLinkClickedEventHandler(this.linkLabel1_LinkClicked);
                    progs.RowCount += 2;
                    RowStyle rs = new RowStyle(SizeType.Absolute, 24);
                    RowStyle rs2 = new RowStyle(SizeType.Absolute, 24);
                    progs.RowStyles.Add(rs);
                    progs.RowStyles.Add(rs2);
                    progs.Controls.Add(l, 0, x * 2);
                    progs.Controls.Add(l2, 1, x * 2);
                    progs.Controls.Add(p, 0, (x * 2) + 1);
                    progs.Controls.Add(p2, 1, (x * 2) + 1);
                    progs.Controls.Add(link, 2, (x * 2) + 1);
                    #endregion
                }
                progs.RowCount += 1;
                progs.RowStyles.Add(new RowStyle(SizeType.Absolute, 24));
                migrate.RunWorkerAsync();
            }
        }

        private LogViewer logviewer;

        private void linkLabel1_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
        {
            LinkLabel l = sender as LinkLabel;
            int x = int.Parse(l.Name.Remove(0, 3));
            if (logviewer != null) logviewer.Close();
            logviewer = new LogViewer(main, main.Migrator.SourceActions[x], main.Migrator.DestinationActions[x]);
            logviewer.Show(this);
        }

        private void migrate_DoWork(object sender, DoWorkEventArgs e)
        {
            if (main != null) main.Migrator.Start(); 
        }

        private void migrate_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            main.EnableNext = true;
        }

        private void saveFileDialog1_FileOk(object sender, CancelEventArgs e)
        {
            XmlWriterSettings set = new XmlWriterSettings();
            set.Indent = true;
            set.IndentChars = ("    ");
            XmlWriter writer = XmlWriter.Create(saveFileDialog1.FileName, set);
            writer.WriteStartElement("migratorlog");
            writer.WriteStartElement("started");
            writer.WriteValue(main.Migrator.SourceActions[0].Status[0].Date);
            writer.WriteEndElement();
            writer.WriteStartElement("ended");
            writer.WriteValue(main.Migrator.DestinationActions[main.Migrator.DestinationActions.Count - 1].Status[main.Migrator.DestinationActions[main.Migrator.DestinationActions.Count - 1].Status.Count - 1].Date);
            writer.WriteEndElement();
            writer.WriteStartElement("actionlogs");
            for (int x = 0; x < main.Migrator.SourceActions.Count; x++)
            {
                processAction((IAction)main.Migrator.SourceActions[x], writer);
                processAction((IAction)main.Migrator.DestinationActions[x], writer);
            }
            writer.WriteEndElement();
            writer.WriteEndElement();
            writer.Flush();
            writer.Close();
        }

        private void processAction(IAction action, XmlWriter writer)
        {
            writer.WriteStartElement("action");
            writer.WriteElementString("name", action.Name);
            writer.WriteElementString("type", action.ActionType.ToString());
            writer.WriteStartElement("events");
            foreach (Event e in action.Status)
            {
                writer.WriteStartElement("event");
                writer.WriteStartElement("occured");
                writer.WriteValue(e.Date);
                writer.WriteEndElement();
                writer.WriteElementString("name", e.Name);
                writer.WriteElementString("message", e.Message);
                writer.WriteElementString("type", e.EventType.ToString());
                writer.WriteEndElement();
            }
            writer.WriteEndElement();
            writer.WriteEndElement();
        }
    }
}
